﻿using System;
using System.Text;

namespace Framework.Common.Html
{
    /// <summary>
    /// html转化为纯文本
    /// </summary>
    public class Html2Text
    {
        private readonly HtmlNode _node;
        /// <summary>
        /// constructor
        /// </summary>
        /// <param name="html"></param>
        public  Html2Text(string html)
        {
            var doc = new HtmlDocument();
            doc.LoadHtml(html);
            _node = doc.DocumentNode;
        }

        /// <summary>
        /// constructor
        /// </summary>
        public Html2Text(HtmlNode node)
        {
            if (node == null) throw new ArgumentNullException("node");
            _node = node;
        }

        #region Public Methods

        /// <summary>
        /// ConvertHtml
        /// </summary>
        /// <returns></returns>
        public string GetText()
        {
            var sbTxt = new StringBuilder();
            ConvertTo(_node, sbTxt);
            return sbTxt.ToString();
        }

        #endregion

        #region Private Methods
        /// <summary>
        /// 
        /// </summary>
        /// <param name="node"></param>
        /// <param name="outText"></param>
        void ConvertTo(HtmlNode node, StringBuilder outText)
        {
            switch (node.NodeType)
            {
                case HtmlNodeType.Comment:
                    break;

                case HtmlNodeType.Document:
                    ConvertContentTo(node, outText);
                    break;

                case HtmlNodeType.Text:
                    // script and style must not be output
                    string parentName = node.ParentNode.Name;
                    if ((parentName == "script") || (parentName == "style"))
                        break;

                    // get text
                    string html = ((HtmlTextNode)node).Text;

                    // is it in fact a special closing node output as text?
                    if (HtmlNode.IsOverlappedClosingElement(html))
                        break;

                    // check the text is meaningful and not a bunch of whitespaces
                    if (!string.IsNullOrWhiteSpace(html))
                    {
                        outText.Append(HtmlEntity.DeEntitize(html));
                    }
                    break;

                case HtmlNodeType.Element:
                    //switch (node.Name)
                    //{
                    //    case "p":
                    //        // treat paragraphs as crlf
                    //        outText.Append(" ");
                    //        break;
                    //}
                    if (node.HasChildNodes)
                    {
                        ConvertContentTo(node, outText);
                    }
                    break;
            }
        }

        void ConvertContentTo(HtmlNode node, StringBuilder outText)
        {
            foreach (HtmlNode subnode in node.ChildNodes)
            {
                ConvertTo(subnode, outText);
            }
        }

        #endregion
    }
}
